﻿using Engine.Graphics;
using SharpDX;
using System.IO;
using System.Runtime.InteropServices;

namespace WorldRacing2
{
    internal class MyOwnVertex
    {
        #region Public Structs

        [StructLayout(LayoutKind.Explicit)]
        public struct Wr2Data : IGameVertex
        {
            [FieldOffset(0)]
            public Vector2 UV;

            [FieldOffset(8)]
            public Vector2 UV2;

            [FieldOffset(16)]
            private Color4 diffuseColor;

            [FieldOffset(32)]
            private Color4 vertexColor;

            public Wr2Data(float u1, float v1, float u2, float v2, Color4 vertexColor)
                : this(u1, v1, u2, v2, vertexColor, Color4.Black)
            {
            }

            public Wr2Data(float u1, float v1, float u2, float v2, Color4 vertexColor, Color4 diffuseColor)
            {
                UV.X = u1;
                UV.Y = v1;
                UV2.X = u2;
                UV2.Y = v2;
                this.vertexColor = vertexColor;
                this.diffuseColor = diffuseColor;
            }

            public Color4 DiffuseColor
            {
                get { return diffuseColor; }
                set { diffuseColor = value; }
            }

            public float Tu
            {
                get { return this.UV.X; }
                set { this.UV.X = value; }
            }

            public float Tv
            {
                get { return this.UV.Y; }
                set { this.UV.Y = value; }
            }

            public float Tu2
            {
                get { return this.UV2.X; }
                set { this.UV2.X = value; }
            }

            public float Tv2
            {
                get { return this.UV2.Y; }
                set { this.UV2.Y = value; }
            }

            public Color4 VertexColor
            {
                get { return this.vertexColor; }
                set { this.vertexColor = value; }
            }

            public static int SizeInBytes()
            {
                return Marshal.SizeOf(typeof(Wr2Data));
            }

            public static Wr2Data FromStream(BinaryReader br, int Version)
            {
                switch (Version)
                {
                    case 0:
                        return LoadVersion0(br);

                    case 1:
                        return LoadVersion1(br);

                    default:
                        throw new System.Exception("World Racing 2 Vertex could not load Version: " + Version.ToString());
                }
            }

            private static Wr2Data LoadVersion0(BinaryReader br)
            {
                Wr2Data vertex = new Wr2Data();
                // vertex Color
                float vertexColorAlpha = br.ReadSingle(); // 1.0 Shadow -> 0.0 no Shadow
                float vertexColorRed = br.ReadSingle();
                float vertexColorGreen = br.ReadSingle();
                float vertexColorBlue = br.ReadSingle();
                // Diffuse Color
                float diffuseAlpha = br.ReadSingle();
                float diffuseRed = br.ReadSingle();
                float diffuseGreen = br.ReadSingle();
                float diffuseBlue = br.ReadSingle();

                vertex.DiffuseColor = new Color4(diffuseRed, diffuseGreen, diffuseBlue, diffuseAlpha);
                vertex.VertexColor = new Color4(vertexColorRed, vertexColorGreen, vertexColorBlue, 0.0f);

                //vertex.DiffuseColor = new Color4(0.4f, 0.4f, 0.4f, 0.0f);
                //vertex.VertexColor = new Color4(1.0f, 0.4f, 0.4f, 1.0f);

                return vertex;
            }

            private static Wr2Data LoadVersion1(BinaryReader br)
            {
                Wr2Data vertex = new Wr2Data();

                // UV Coordinates
                vertex.Tu = br.ReadSingle();
                vertex.Tv = br.ReadSingle();
                vertex.Tu2 = br.ReadSingle();
                vertex.Tv2 = br.ReadSingle();

                // vertex Color
                float vertexColorAlpha = br.ReadSingle(); // 1.0 Shadow -> 0.0 no Shadow
                float vertexColorRed = br.ReadSingle();
                float vertexColorGreen = br.ReadSingle();
                float vertexColorBlue = br.ReadSingle();
                // Diffuse Color
                float diffuseAlpha = br.ReadSingle();
                float diffuseRed = br.ReadSingle();
                float diffuseGreen = br.ReadSingle();
                float diffuseBlue = br.ReadSingle();

                vertex.DiffuseColor = new Color4(diffuseRed, diffuseGreen, diffuseBlue, diffuseAlpha);
                vertex.VertexColor = new Color4(vertexColorRed, vertexColorGreen, vertexColorBlue, 0.0f);

                //vertex.DiffuseColor = new Color4(0.4f, 0.4f, 0.4f, 0.0f);
                //vertex.VertexColor = new Color4(1.0f, 0.4f, 0.4f, 1.0f);

                return vertex;
            }

            public void ToStream(BinaryWriter bw)
            {
                bw.Write(this.Tu);
                bw.Write(this.Tv);

                bw.Write(this.Tu2);
                bw.Write(this.Tv2);

                bw.Write(this.vertexColor.Alpha);
                bw.Write(this.vertexColor.Red);
                bw.Write(this.vertexColor.Green);
                bw.Write(this.vertexColor.Blue);

                bw.Write(this.DiffuseColor.Alpha);
                bw.Write(this.DiffuseColor.Red);
                bw.Write(this.DiffuseColor.Green);
                bw.Write(this.DiffuseColor.Blue);
            }

            public int GetCurrentVersion()
            {
                // Version 1: 01.02.2017
                return 1;
            }

            public IGameVertex UpdateWithEngineVertexData(Engine.Graphics.VertexStructures.MyOwnVertex.PositionNormalTextured positionNormalTextured)
            {
                this.UV = positionNormalTextured.UV;
                return this;
            }
        }

        #endregion Public Structs
    }
}